﻿#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <thread>
#include <queue>
#include <vector>
#include <future>
#include <memory>
//模板线程池，提速使用
class ThreadPool {
public:
    ThreadPool(const ThreadPool&) = delete;
    ThreadPool& operator=(ThreadPool&) = delete;
    static ThreadPool& Instance(){
        static ThreadPool ins;
        return ins;
    }
    using Task = std::packaged_task<void()>;
    ~ThreadPool() {
        stop();
    }
    template <class F, class ...Args>
    auto commit(F && f, Args && ...args) -> std::future<decltype(f(args...))> {
        using Rettype = decltype(f(args...));
        if (_stop.load())
            return std::future<Rettype>{};

        auto task = std::make_shared<std::packaged_task<Rettype()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        std::future<Rettype> res = task->get_future();
        {
            std::lock_guard<std::mutex> lk(m);
            //tasks.emplace([this, task]() {(*task)(); });
            tasks.emplace(std::move(*task));
        }
        cv.notify_all();
        return res;
    }
private:
    ThreadPool(unsigned int num = 20):_stop(false) {
        if (num < 1) {
            thread_num = 1;
        }
        else {
            thread_num = num;
        }
        start();
    }
    void start() {
        threads.emplace_back([this]() {
            while (!_stop.load()) {
                Task task;
                {
                    std::unique_lock<std::mutex> lk(m);
                    cv.wait(lk, [this]() {
                        return !tasks.empty() || _stop.load();
                    });
                    if (tasks.empty() && _stop.load())
                        return;
                    task = std::move(tasks.front());
                    tasks.pop();
                }
                thread_num --;
                task();
            }	thread_num ++;
        });
    }
    void stop() {
        _stop.store(true);
        cv.notify_all();
        for (auto& t : threads) {
            if (t.joinable()) {
                t.join();
            }
        }
    }
private:
    std::vector<std::thread> threads;
    std::queue<Task> tasks;
    std::atomic_bool _stop;
    std::atomic_int thread_num;
    std::mutex m;
    std::condition_variable cv;
};


#endif // THREAD_POOL_H
